{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "1800514a",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "**优化说明**：\n",
    "- 为代码单元添加中文注释；\n",
    "- 为缺少 docstring 的函数插入简要 docstring模板；\n",
    "- 为常见 import 添加简短中文注释；\n",
    "- 对 pd.read_csv 补充 low_memory=False，规范 plt.show()，修正不一致；\n",
    "  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "23757e5a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 1: 导入依赖库、绘图/可视化 ===\n",
    "import numpy as np # 数据处理最重要的模块\n",
    "import pandas as pd # 数据处理最重要的模块\n",
    "import scipy.stats as stats # 统计模块\n",
    "import scipy  # 科学计算\n",
    "# import pymysql  # 导入数据库模块\n",
    "\n",
    "from datetime import datetime # 时间模块\n",
    "import statsmodels.formula.api as smf  # OLS regression\n",
    "\n",
    "# import pyreadr # read RDS file\n",
    "\n",
    "from matplotlib import style  # 绘图\n",
    "import matplotlib.pyplot as plt  # 画图模块\n",
    "import matplotlib.dates as mdates  # 绘图\n",
    "\n",
    "\n",
    "from matplotlib.font_manager import FontProperties # 作图中文\n",
    "from pylab import mpl\n",
    "#mpl.rcParams['font.sans-serif'] = ['SimHei']\n",
    "#plt.rcParams['font.family'] = 'Times New Roman'\n",
    "\n",
    "\n",
    "#输出矢量图 渲染矢量图\n",
    "%matplotlib inline\n",
    "%config InlineBackend.figure_format = 'svg'\n",
    "\n",
    "from IPython.core.interactiveshell import InteractiveShell # jupyter运行输出的模块\n",
    "#显示每一个运行结果\n",
    "InteractiveShell.ast_node_interactivity = 'all'\n",
    "\n",
    "#设置行不限制数量\n",
    "#pd.set_option('display.max_rows',None)\n",
    "\n",
    "#设置列不限制数量\n",
    "pd.set_option('display.max_columns', None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2b31e2a0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 2: 读取数据、数据清洗/转换 ===\n",
    "data = pd.read_csv('datasets/000001.csv', low_memory=False)\n",
    "data['Day'] = pd.to_datetime(data['Day'],format='%Y/%m/%d')\n",
    "data.set_index('Day', inplace = True)\n",
    "data.sort_values(by = ['Day'],axis=0, ascending=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f4e1a4c0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 3: 通用计算/执行 ===\n",
    "data_new = data['1995-01':'2024-09'].copy()\n",
    "data_new['Close'] = pd.to_numeric(data_new['Close'])\n",
    "data_new['Preclose'] = pd.to_numeric(data_new['Preclose'])\n",
    "# 计算000001上证指数日收益率 两种：\n",
    "data_new['Raw_return'] = data_new['Close'] / data_new['Preclose'] - 1\n",
    "data_new"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ba8010d8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 4: 通用计算/执行 ===\n",
    "Month_data = data_new.resample('ME')['Raw_return'].apply(lambda x: (1+x).prod() - 1).to_frame()\n",
    "Month_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c4140c70",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 5: 通用计算/执行 ===\n",
    "Quarter_data = data_new.resample('QE')['Raw_return'].apply(lambda x: (1+x).prod() - 1).to_frame()\n",
    "Quarter_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f33804ad",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 6: 通用计算/执行 ===\n",
    "Year_data = data_new.resample('YE')['Raw_return'].apply(lambda x: (1+x).prod() - 1).to_frame()\n",
    "Year_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4550efe7",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 7: 读取数据、数据清洗/转换 ===\n",
    "inflation = pd.read_csv('datasets/inflation.csv', low_memory=False)\n",
    "inflation['month'] = pd.to_datetime(inflation['month'],format='%Y/%m/%d')\n",
    "inflation.set_index('month',inplace=True)\n",
    "inflation"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dfed2436",
   "metadata": {},
   "source": [
    "# 月度数据的预测\n",
    "\n",
    "A simple linear regression of an asset return on one or a few lagged predictors of interest is the most popular econometric approach for testing for return predictability. For simplicity, consider a univariate predictive regression of the period- $(t + 1)$ stock market return $r_{t+1}$ on a single predictor variable $x_t$:\n",
    "$$\n",
    "r_{t+1}=\\alpha+\\beta x_{t}+\\varepsilon_{t+1}\n",
    "$$\n",
    "where $\\varepsilon_{t+1}$ is a zero-mean, unpredictable disturbance term. When $x_t$ is the inflation rate, dividend yield, book-to-price ratio, or turnover. Many researchers find that $\\beta$ is significantly different from zero; that is, there is in-sample evidence of stock market return predictability.\n",
    "\n",
    "* H0:$\\beta = 0$\n",
    "* H1:$\\beta \\ne 0$(我们需要通过理论分析，得出$\\beta$的符号)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a1788daa",
   "metadata": {},
   "source": [
    "## 模型1 通货膨胀与股票预期收益率\n",
    "\n",
    "在经济处于高通货膨胀时期, 人们无不希望能找到一种能有效抵御通货憉胀风险的资产 以避免或降低财富缩水, 而金融资产由于其流动性好, 往往成为人们考虑的首选, 这其中股票市场收益率与通货政胀率之间的关系尤为引人关注。事实上, 早在20世纪30年代费雪就提出了著名的“费雪假说”, 费雪预言, 预期通货膨胀与名义资产回报之间具有正相关关系, 名义资产天生地是抵御通货膨胀的保值品。费雪假说提出后, 经济理论界将该假说引中至股票市场, 并由此得出了股票市场相关的费雪效应假说, 即当通货膨胀率发生变化时, 股票名义收益率也会相应地做出调整, 股票实际收益率保持不变, 从而使得股票名义收益率应该与预期的通货通胀率之间存在一一对应的正向关系, 因此, 股票能够很好地对冲通货膨胀风险, 是一种良好的通货膨胀保值品。\n",
    "\n",
    "然而较高的通货膨胀往往意味着投资环境的恶化和和未来经济环境的悲观预期增加，也是经济衰退的重要先行指标，经济活动的萎缩带来上市公司盈利水平的下降，从而股票市场的回报率是下降的。\n",
    "\n",
    "$$\n",
    "r_{t+1} = \\alpha + \\beta*CPI_{t-1} + \\varepsilon_{t+1}\n",
    "$$\n",
    "\n",
    "两个假设：\n",
    "\n",
    "* H1： $\\beta > 0$\n",
    "\n",
    "* H2： $\\beta < 0$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cc4319d9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 8: 数据清洗/转换 ===\n",
    "reg_data = pd.merge(Month_data, inflation, left_index=True, right_index=True,how='left')\n",
    "reg_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "80febf43",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 9: 通用计算/执行 ===\n",
    "# 导出数据\n",
    "reg_data.to_csv('datasets/reg_data.csv')\n",
    "# save as excel\n",
    "reg_data.to_excel('datasets/reg_data.xlsx')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "09cf0ad8",
   "metadata": {},
   "source": [
    "## 作图 Plot"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "47e7f47d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 10: 绘图/可视化 ===\n",
    "# Plot the China's stock market return and inflation into one graph\n",
    "fig, ax1 = plt.subplots(figsize=(12,4))\n",
    "# the linewidth and marker size are set to be very small\n",
    "ax1.plot(reg_data['Raw_return'],color='red',marker='o',linewidth=0.8,\n",
    "         markersize=4,\n",
    "         linestyle='--',label='China Stock Market Return')\n",
    "ax1.set_ylabel('China Stock Market Return',color='red')\n",
    "#ax1.set_xlabel('Month')\n",
    "\n",
    "# 设置x轴的日期显示格式\n",
    "data_format = mdates.DateFormatter('%Y')\n",
    "ax1.xaxis.set_major_formatter(data_format)\n",
    "ax1.xaxis.set_major_locator(mdates.YearLocator())\n",
    "\n",
    "# 转置x轴的日期显示格式\n",
    "plt.xticks(rotation = 90)\n",
    "\n",
    "ax2 = ax1.twinx()\n",
    "ax2.plot(reg_data['cpi'].shift(2),color='blue',marker='o',linewidth=0.8,\n",
    "         markersize=4,\n",
    "         linestyle='-',label='China Inflation')\n",
    "\n",
    "ax2.set_ylabel('China Inflation',color='blue')\n",
    "\n",
    "plt.title('China Stock Market Return and Inflation')\n",
    "\n",
    "# change the legend into one box\n",
    "lines, labels = ax1.get_legend_handles_labels()\n",
    "lines2, labels2 = ax2.get_legend_handles_labels()\n",
    "ax2.legend(lines + lines2, labels + labels2, loc='upper right')\n",
    "\n",
    "# save figure\n",
    "fig.savefig('images/China Stock Market Return and Inflation.png',dpi = 1000,bbox_inches='tight')\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "03d5b0a0",
   "metadata": {},
   "source": [
    "## 描述性统计 Summary\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a26826ac",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 11: 通用计算/执行 ===\n",
    "reg_data['cpi'].describe().round(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8531e691",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 12: 通用计算/执行 ===\n",
    "reg_data['cpi'].skew()\n",
    "reg_data['cpi'].kurt()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4c29e972",
   "metadata": {},
   "source": [
    "## OLS 回归结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7a21447f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 13: 建模/训练 ===\n",
    "reg_data['lcpi'] = reg_data['cpi'].shift(2)/100\n",
    "model_cpi = smf.ols('Raw_return ~ lcpi',\n",
    "                 data=reg_data['2000-01':'2024-09']).fit(\n",
    "                     cov_type='HAC', cov_kwds={'maxlags': 6})\n",
    "print(model_cpi.summary())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6621748e",
   "metadata": {},
   "source": [
    "## 预期收益率 Expected Return / Conditional Return"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bb323825",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 14: 绘图/可视化 ===\n",
    "data = reg_data['2000-01':'2024-09'].copy()\n",
    "data['fitted_return'] =  model_cpi.fittedvalues\n",
    "\n",
    "fig = plt.figure(figsize=(10, 5))\n",
    "plt.plot('Raw_return',\n",
    "         '-r',\n",
    "         label='ret',\n",
    "         linewidth=1,\n",
    "         data=data)\n",
    "plt.plot('fitted_return',\n",
    "         '-b',\n",
    "         label='Fitted Return',\n",
    "         linewidth=1,\n",
    "         data=data)\n",
    "plt.title(\"China's Stock Market\")\n",
    "plt.xlabel('Month')  # 画图的x轴名称\n",
    "plt.ylabel('Return')  # 画图的y轴名称\n",
    "\n",
    "# 设置x轴的日期显示格式\n",
    "data_format = mdates.DateFormatter('%Y')\n",
    "ax1.xaxis.set_major_formatter(data_format)\n",
    "ax1.xaxis.set_major_locator(mdates.YearLocator())\n",
    "\n",
    "# 转置x轴的日期显示格式\n",
    "plt.xticks(rotation = 90)\n",
    "plt.legend()\n",
    "fig.savefig('images/fitted_return.pdf', bbox_inches='tight')  # 保存为 PDF（矢量格式，更清晰）\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "20e51ec0",
   "metadata": {},
   "source": [
    "## 季度结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "198a0f92",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 15: 通用计算/执行 ===\n",
    "Q_reg_data = reg_data['1995-01':'2024-09'].resample('QE').apply({\n",
    "    'Raw_return':\n",
    "    lambda x: (1 + x).prod() - 1,\n",
    "    'cpi':\n",
    "    lambda x: sum(x)\n",
    "})\n",
    "Q_reg_data['lag_cpi'] = Q_reg_data['cpi'].shift(1)\n",
    "Q_reg_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "797676ce",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 16: 绘图/可视化 ===\n",
    "plt.style.available"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "688f6cf3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 17: 绘图/可视化 ===\n",
    "# Change the figure style\n",
    "plt.style.use('classic')\n",
    "fig = plt.figure(figsize=(15, 5))\n",
    "ax1 = fig.add_subplot(1, 1, 1)  #(x, x, x)这里前两个表示几*几的网格，最后一个表示第几子图\n",
    "\n",
    "ax1.plot(Q_reg_data['Raw_return'],\n",
    "         color='blue',\n",
    "         marker='.',\n",
    "         linestyle='-',\n",
    "         linewidth=1,\n",
    "         markersize=6,\n",
    "         alpha=0.4,\n",
    "         label='Market Return')\n",
    "ax1.set_xlabel('Q')  # 设置横坐标标签\n",
    "ax1.set_ylabel('return')  # 设置左边纵坐标标签\n",
    "#ax1.legend(loc=2)  # 设置图例在左上方\n",
    "ax1.set_title(\"CPI and China's stock market excess return: Quarterly 1995-2024\")  # 给整张图命名\n",
    "\n",
    "# 设置x轴的日期显示格式\n",
    "data_format = mdates.DateFormatter('%Y')\n",
    "ax1.xaxis.set_major_formatter(data_format)\n",
    "ax1.xaxis.set_major_locator(mdates.YearLocator())\n",
    "plt.xticks(rotation = 90) # 转置x轴的日期显示格式\n",
    "\n",
    "ax2 = ax1.twinx()  #twinx()函数表示共享x轴\n",
    "ax2.plot(Q_reg_data['lag_cpi'],\n",
    "         color='red',\n",
    "         marker='o',\n",
    "         linestyle='-',\n",
    "         linewidth=1,\n",
    "         markersize=2,\n",
    "         alpha=0.7,\n",
    "         label='CPI')\n",
    "ax2.set_ylabel('CPI')  # 设置右边纵坐标标签\n",
    "#ax2.legend(loc=1)  # 设置图例在右上方\n",
    "\n",
    "# change the legend into one box\n",
    "lines, labels = ax1.get_legend_handles_labels()\n",
    "lines2, labels2 = ax2.get_legend_handles_labels()\n",
    "ax2.legend(lines + lines2, labels + labels2, loc='upper right')\n",
    "\n",
    "fig.savefig('Qcpi.pdf', bbox_inches='tight')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ffffd4a7",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 18: 建模/训练 ===\n",
    "Q_reg_data['lcpi'] = Q_reg_data['cpi'].shift(1)\n",
    "model_qcpi = smf.ols('Raw_return ~ lcpi',\n",
    "                 data=Q_reg_data['2000':'2024-09']).fit(\n",
    "                     cov_type='HAC', cov_kwds={'maxlags': 2})\n",
    "print(model_qcpi.summary())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "087c6d72",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 19: 绘图/可视化 ===\n",
    "data = Q_reg_data['2000-01':'2024-09'].copy()\n",
    "data['fitted_return'] =  model_cpi.fittedvalues\n",
    "\n",
    "fig = plt.figure(figsize=(10, 5))\n",
    "plt.plot('Raw_return',\n",
    "         '-r',\n",
    "         label='ret',\n",
    "         linewidth=1,\n",
    "         data=data)\n",
    "plt.plot('fitted_return',\n",
    "         '-b',\n",
    "         label='Fitted Return',\n",
    "         linewidth=1,\n",
    "         data=data)\n",
    "plt.title(\"China's Stock Market\")\n",
    "plt.xlabel('Quarter')  # 画图的x轴名称\n",
    "plt.ylabel('Return')  # 画图的y轴名称\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "16882322",
   "metadata": {},
   "source": [
    "## 长期预测 Long Horizon Forecast"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5ef089d8",
   "metadata": {},
   "source": [
    "$$\n",
    "r_{t+1} + r_{t+2} + r_{t+3}  =\\alpha+\\beta x_{t}+\\varepsilon_{t+1}\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "13b273e1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 20: 通用计算/执行 ===\n",
    "reg_data['next_ret'] = reg_data['Raw_return'].shift(-1) + 1\n",
    "reg_data['next_ret2'] = reg_data['Raw_return'].shift(-2) + 1\n",
    "reg_data['next_ret3'] = reg_data['Raw_return'].shift(-3) + 1\n",
    "reg_data['future_3month_return'] = reg_data['next_ret'] * reg_data['next_ret2'] * reg_data['next_ret3'] - 1\n",
    "reg_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "37c44294",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 21: 建模/训练 ===\n",
    "model_cpi_3month = smf.ols('future_3month_return ~ lcpi',\n",
    "                 data=reg_data['2000-01':'2024-09']).fit(\n",
    "                     cov_type='HAC', cov_kwds={'maxlags': 6})\n",
    "print(model_cpi_3month.summary())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4a107ab7",
   "metadata": {},
   "source": [
    "# 整理结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "38b5d2ab",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 22: 导入依赖库 ===\n",
    "from statsmodels.iolib.summary2 import summary_col\n",
    "\n",
    "info_dict = {'No. observations': lambda x: f\"{int(x.nobs):d}\"}\n",
    "\n",
    "results_table = summary_col(results=[model_cpi, model_cpi_3month, model_qcpi],\n",
    "                            float_format='%0.3f', #数据显示的格式，默认四位小数\n",
    "                            stars=True, # 是否有*，True为有\n",
    "                            model_names=[\"Next Month's Return\", \"Next 3 Months' Return\", 'Quarter Return'],\n",
    "                            info_dict=info_dict,\n",
    "                            regressor_order=['Intercept', 'lcpi'])\n",
    "\n",
    "results_table.add_title(\n",
    "    'Table - OLS Regressions: Forecast Stock Market Return')\n",
    "\n",
    "print(results_table)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "712e662f",
   "metadata": {},
   "source": [
    "# CPI的自相关性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "09be7fd3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 23: 建模/训练 ===\n",
    "reg_data['lcpi'] = reg_data['cpi'].shift(1)\n",
    "model_cpiself = smf.ols('cpi~lcpi',\n",
    "                 data=reg_data['2000-01':'2024-09']).fit(\n",
    "                     cov_type='HAC', cov_kwds={'maxlags': 6})\n",
    "print(model_cpiself.summary())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8d21d831",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 24: 建模/训练 ===\n",
    "model_cpiself = smf.ols('Raw_return~cpi',\n",
    "                 data=reg_data['2000-01':'2024-09']).fit(\n",
    "                     cov_type='HAC', cov_kwds={'maxlags': 6})\n",
    "print(model_cpiself.summary())"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
